package com.icesoft.base.manager.security.impl;

import com.icesoft.base.manager.helper.AuthUser;
import com.icesoft.base.manager.helper.SecurityUtils;
import com.icesoft.base.manager.security.config.ApiMatchAuthority;
import com.icesoft.base.manager.security.suppose.IWhiteIpService;
import com.icesoft.core.web.helper.RequestHold;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;

@Component
@Slf4j
@AllArgsConstructor
public class RbacService {
    private static AntPathMatcher antPathMatcher = new AntPathMatcher();
    private Set<IWhiteIpService> whiteIpServices;

    public boolean hasEndpointPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if (principal instanceof AuthUser) {
            if (SecurityUtils.isSuperAdmin((AuthUser) principal)) {
                return true;
            }
        }
        String userIp = RequestHold.getRemoteIP(request);
        if (whiteIpServices.stream().map(IWhiteIpService::getWhiteIps).filter(Objects::nonNull).flatMap(Set::stream)
                .anyMatch(userIp::equals)) {
            return true;
        }
        log.info("非白名单IP：{}", userIp);
        return false;
    }

    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if (principal == null || !authentication.isAuthenticated()) {
            log.trace("用户未授权:{}，无法访问请求：{}", principal, request.getRequestURI());
            return false;
        }
        String urlNoContextPath = RequestHold.getRequestUrl(request);
        Set<ApiMatchAuthority> authoritySet = SecurityUtils.getApiMatchAuthority(authentication);

        boolean hasPermission = isMatch(authoritySet, urlNoContextPath);
        if (!hasPermission) {
            log.info("用户：[{}]，没有请求权限：[{}], 拥有权限：[{}]" , authentication.getName(),urlNoContextPath,authoritySet);
        } else {
            log.trace("用户：[{}]允许访问接口：[{}]", authentication.getName(), urlNoContextPath);
        }
        return hasPermission;
    }

    private static boolean isMatch(Set<ApiMatchAuthority> authoritySet, String urlNoContextPath) {
        return authoritySet.stream().map(ApiMatchAuthority::getPatterns).flatMap(Collection::stream)
                .anyMatch(pattern->antPathMatcher.match(pattern, urlNoContextPath));
    }

}
